package com.library.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.library.entity.BorrowRecord;
import com.library.mapper.BorrowRecordMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * 借阅记录服务
 */
@Service
@RequiredArgsConstructor
public class BorrowRecordService extends ServiceImpl<BorrowRecordMapper, BorrowRecord> {
    
    private final BorrowRecordMapper borrowRecordMapper;
    private final BookService bookService;
    
    @Value("${library.max-borrow-days:30}")
    private Integer maxBorrowDays;
    
    @Value("${library.max-borrow-count:5}")
    private Integer maxBorrowCount;
    
    @Value("${library.overdue-fine-per-day:0.5}")
    private BigDecimal overdueFinePerDay;
    
    /**
     * 借书
     */
    @Transactional(rollbackFor = Exception.class)
    public void borrowBook(Long bookId) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        // 检查用户当前借阅数量
        Long borrowCount = this.count(new LambdaQueryWrapper<BorrowRecord>()
                .eq(BorrowRecord::getUserId, userId)
                .eq(BorrowRecord::getStatus, "BORROWED"));
        
        if (borrowCount >= maxBorrowCount) {
            throw new RuntimeException("借阅数量已达上限（" + maxBorrowCount + "本）");
        }
        
        // 检查图书是否可借
        if (!bookService.isBookAvailable(bookId)) {
            throw new RuntimeException("图书库存不足");
        }
        
        // 减少库存
        bookService.decreaseStock(bookId);
        
        // 创建借阅记录
        BorrowRecord record = new BorrowRecord();
        record.setUserId(userId);
        record.setBookId(bookId);
        record.setBorrowDate(LocalDateTime.now());
        record.setDueDate(LocalDateTime.now().plusDays(maxBorrowDays));
        record.setStatus("BORROWED");
        record.setRenewCount(0);
        record.setFine(BigDecimal.ZERO);
        
        this.save(record);
    }
    
    /**
     * 还书
     */
    @Transactional(rollbackFor = Exception.class)
    public void returnBook(Long recordId) {
        BorrowRecord record = this.getById(recordId);
        
        if (record == null) {
            throw new RuntimeException("借阅记录不存在");
        }
        
        if (!"BORROWED".equals(record.getStatus()) && !"OVERDUE".equals(record.getStatus())) {
            throw new RuntimeException("该图书已归还");
        }
        
        // 计算罚金
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(record.getDueDate())) {
            long overdueDays = ChronoUnit.DAYS.between(record.getDueDate(), now);
            BigDecimal fine = overdueFinePerDay.multiply(BigDecimal.valueOf(overdueDays));
            record.setFine(fine);
        }
        
        // 更新记录
        record.setReturnDate(now);
        record.setStatus("RETURNED");
        this.updateById(record);
        
        // 增加库存
        bookService.increaseStock(record.getBookId());
    }
    
    /**
     * 续借
     */
    public void renewBook(Long recordId) {
        BorrowRecord record = this.getById(recordId);
        
        if (record == null) {
            throw new RuntimeException("借阅记录不存在");
        }
        
        if (!"BORROWED".equals(record.getStatus())) {
            throw new RuntimeException("只能续借借出中的图书");
        }
        
        if (record.getRenewCount() >= 2) {
            throw new RuntimeException("续借次数已达上限");
        }
        
        // 延长归还日期
        record.setDueDate(record.getDueDate().plusDays(maxBorrowDays));
        record.setRenewCount(record.getRenewCount() + 1);
        this.updateById(record);
    }
    
    /**
     * 分页查询借阅记录
     */
    public Page<BorrowRecord> pageRecords(Integer current, Integer size, Long userId, String status) {
        Page<BorrowRecord> page = new Page<>(current, size);
        return borrowRecordMapper.selectRecordPage(page, userId, status);
    }
    
    /**
     * 获取当前用户的借阅记录
     */
    public Page<BorrowRecord> getMyRecords(Integer current, Integer size, String status) {
        Long userId = StpUtil.getLoginIdAsLong();
        return pageRecords(current, size, userId, status);
    }
    
    /**
     * 检查并更新逾期记录
     */
    public void checkOverdueRecords() {
        LocalDateTime now = LocalDateTime.now();
        
        LambdaQueryWrapper<BorrowRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BorrowRecord::getStatus, "BORROWED")
               .lt(BorrowRecord::getDueDate, now);
        
        List<BorrowRecord> overdueRecords = this.list(wrapper);
        
        for (BorrowRecord record : overdueRecords) {
            record.setStatus("OVERDUE");
            this.updateById(record);
        }
    }
}

